Mål 🎯

  • Sjå korleis me får inn datasettet og korleis me kan jobba med det
  • Litt statistikk
  • Litt visualisering
  • Korleis bruke NDLA til å få hjelp til koden

Dataanalyse

Korleis jobbe med csv-fila vår?

Steg 0 - få inn datasettet

Siste oppdaterte variant - all data + sortering.

Rett inn i jupyter lab 🚀

https://raw.githubusercontent.com/lektorodd/tof1-2425/refs/heads/main/data/vassforbruk-2425-brei.csv



  1. Kopier lenka

  2. Opne Jupyter Lab og .ipynb-fila

  3. Klikk på Fil ➡️ Open from URL

  4. Lim inn lenka og klikk “Open” 🪄

Steg 0 - installere seaborn

I Jupyter Lab desktop er ikkje seaborn installert som standard. Dette installerer me lett med å skriva:

!pip install seaborn

i ei celle i notatblokka.

Restarte kjerna

Når du har installert seaborn må du restarte kjerna. Velg Kernel ➡️ Restart Kernel.

Lese inn med Pandas

Ser på csv-fila korleis ho ser ut:

Det er to rader med kommentarar, ei rad med overskrifter og så data.

Vidare er verdiane separert med komma, og desimalteikn er punktum.

import pandas as pd

# Les inn datafila. Hoppar over dei to første radene
df = pd.read_csv("vassforbruk-2425-brei.csv", skiprows=2)

# Ser på dei 5 første radene
df.head()
elev dato ukedag håndvask dusj drikkevann toalett matlaging oppvask klesvask annet
0 1 2024-09-16 mandag 0.20 264.0 3.0 30.0 15.0 18.0 55.0 0.0
1 1 2024-09-17 tirsdag 0.35 312.0 2.5 35.0 12.0 18.0 0.0 0.0
2 1 2024-09-18 onsdag 0.20 204.0 2.5 30.0 10.0 18.0 55.0 0.0
3 1 2024-09-19 torsdag 6.00 252.0 2.5 28.0 12.0 18.0 0.0 0.0
4 1 2024-09-20 fredag 8.00 240.0 3.0 30.0 12.0 18.0 55.0 0.0

Oversikt

Den enklaste måten å få eit overblikk over datamaterialet på er å nytta .describe()-funksjonen:

df.describe()
elev håndvask dusj drikkevann toalett matlaging oppvask klesvask annet
count 217.000000 215.000000 217.000000 217.000000 217.000000 216.000000 217.000000 217.000000 217.000000
mean 16.000000 17.623452 97.319737 3.655668 27.308295 2.314699 9.238246 10.710046 2.910138
std 8.964952 17.461910 107.356588 23.332927 16.868476 5.367266 15.427669 17.985546 14.580069
min 1.000000 0.100000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
25% 8.000000 5.707500 8.600000 1.100000 16.000000 0.000000 0.000000 0.000000 0.000000
50% 16.000000 13.000000 65.000000 2.000000 24.000000 0.300000 4.000000 0.000000 0.000000
75% 24.000000 21.700000 140.000000 2.800000 36.000000 1.525000 10.000000 13.000000 0.300000
max 31.000000 82.000000 585.000000 345.000000 81.000000 45.000000 100.000000 100.000000 200.000000

Kva betyr det?

  • count: kor mange verdiar som er i kvar kolonne
  • mean: gjennomsnittet av verdiane i kvar kolonne
  • std: standardavviket til verdiane i kvar kolonne
  • min: den minste verdien i kvar kolonne
  • 25%: 25% av verdiane er mindre enn dette
  • 50%: 50% av verdiane er mindre enn dette
  • 75%: 75% av verdiane er mindre enn dette
  • max: den største verdien i kvar kolonne

Standardavvik

By M. W. Toews - Own work, based (in concept) on figure by Jeremy Kemp, on 2005-02-09, CC BY 2.5, https://commons.wikimedia.org/w/index.php?curid=1903871

Ser på dusjkolonna for døme:

df["dusj"].describe()
count    217.000000
mean      97.319737
std      107.356588
min        0.000000
25%        8.600000
50%       65.000000
75%      140.000000
max      585.000000
Name: dusj, dtype: float64

Gjennomsnittet er ca. 97.3 L og standardavviket er ca. 107.4L.

Det betyr at omlag 68% av verdiane ligg i i intervallet

\[97.3 \pm 107.4 = [0, 184.5]\]

(Merk at den lavaste verdien er 0, sidan ingen har levert tilbake vatn når dei har dusja… (og \(97.3 - 107.4 = -10.1\)))

Samtidig er 25%-persentilen 8.6 L og 75%-persentilen 140.0L.

Det betyr at 50% av verdiane ligg i intervallet

\[[8.6, 140.0]\]

Slike opplysingar kan me visualisera med eit boksplott:

import seaborn as sns
sns.set_theme(style="ticks", palette="pastel")

sns.boxplot(data=df[["dusj", "toalett", "drikkevann"]])

Rydde i datasettet

Frå breitt til langt format

Når me jobbar med datasett, er det ofte lurt å ha data i “long format” i staden for “wide format”. Dette er meir fleksibelt og gjer det enklare å jobba med data.

Datasettet vårt har breitt format - kvar kolonne er ein variabel. Me vil ha det i langt format - kvar rad er ein observasjon.

elev dato ukedag håndvask dusj drikkevann toalett matlaging oppvask klesvask annet
0 1 2024-09-16 mandag 0.20 264.0 3.0 30.0 15.0 18.0 55.0 0.0
1 1 2024-09-17 tirsdag 0.35 312.0 2.5 35.0 12.0 18.0 0.0 0.0
2 1 2024-09-18 onsdag 0.20 204.0 2.5 30.0 10.0 18.0 55.0 0.0

Omforma datasettet

df_lang = pd.melt(
    df, 
    id_vars=["elev", "dato", "ukedag"],
    value_vars=[
        "håndvask", "dusj", "drikkevann", "toalett", 
        "matlaging", "oppvask", "klesvask", "annet"],
    var_name="kategori",
    value_name="forbruk",
)

df_lang

Omforma datasettet

elev dato ukedag kategori forbruk
0 1 2024-09-16 mandag håndvask 0.20
1 1 2024-09-17 tirsdag håndvask 0.35
2 1 2024-09-18 onsdag håndvask 0.20
3 1 2024-09-19 torsdag håndvask 6.00
4 1 2024-09-20 fredag håndvask 8.00
... ... ... ... ... ...
1731 31 2024-09-18 onsdag annet 9.30
1732 31 2024-09-19 torsdag annet 10.30
1733 31 2024-09-20 fredag annet 0.00
1734 31 2024-09-21 lørdag annet 18.00
1735 31 2024-09-22 søndag annet 8.20

1736 rows × 5 columns

Plot - ulike døme

Boksplott

import seaborn as sns
import matplotlib.pyplot as plt

plt.figure(figsize=(12, 9))
sns.set_theme(style="ticks", palette="pastel")

# boksplot for dusjing - fargekoda etter vekedag
sns.boxplot(x="kategori", y="forbruk",
            hue="ukedag", palette=["m","m","g","m","m","g","g"],
            data=df_lang[df_lang["kategori"]=="dusj"])

# ta vekk ramma
sns.despine(offset=10, trim=True)

# legg til tittel
plt.title("Boksplot for dusjing - fargekoda etter vekedag",
          fontsize=16, fontweight="bold")

# vise plottet
plt.show()

Boksplott

Stolpediagram - totalforbruk per kategori

import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

# Lagar tom figur
plt.figure(figsize=(12, 9))

# Stolpediagram. estimator=sum gjer at me får *totalt forbruk* per kategori
sns.barplot(x="kategori", y="forbruk", data=df_lang, estimator=sum)

# Pynting
plt.title("Totalt vannforbruk per kategori")
plt.xlabel("Kategori")
plt.ylabel("Totalt forbruk")
plt.xticks(rotation=45)
plt.grid()
plt.show()

Stolpediagram - totalforbruk per kategori

Gjennomsnittleg forbruk per vekedag

# tom figur
plt.figure(figsize=(10, 6))

# Linjediagram. Her er estimator sett til mean når me ikkje har oppgitt anna
sns.lineplot(x="ukedag", y="forbruk", data=df_lang)

# pynt - kan endra storleik osb på tekst
plt.title("Gjennomsnittlig vannforbruk per ukedag", fontsize=24)
plt.xlabel("ukedag", fontweight="bold")
plt.ylabel("Gjennomsnittlig forbruk", fontweight="bold")
plt.show()

Gjennomsnittleg forbruk per vekedag

Utrekningar per elev

Me kan gjera ulike berekningar i langt format. La oss gruppera datasettet etter “elev” med .groupby()-funksjonen.

elev_forbruk = df_lang.groupby("elev")["forbruk"].sum()
elev_forbruk.head()
elev
1    2574.25
2     820.20
3    1040.80
4    1132.30
5    1519.35
Name: forbruk, dtype: float64

Utrekningar per elev

Me kan gjera ulike berekningar i langt format. La oss gruppera datasettet etter “elev” med .groupby()-funksjonen.

elev_forbruk = df_lang.groupby("elev")["forbruk"].sum().sort_values(ascending=False)
elev_forbruk.head()
elev
23    3883.50
8     3092.70
1     2574.25
13    2171.50
14    2039.20
Name: forbruk, dtype: float64

Utrekningar per elev

Me kan òg rekna ut gjennomsnittet for alle elevane.

snittforbruk = elev_forbruk.mean()
print(snittforbruk)
1196.3503075268818

Plotte

Me kan plotte desse verdiane for å sjå korleis dei fordeler seg.

plt.figure(figsize=(12, 6))

# Stolpediagram - sortert etter totalt forbruk
sns.barplot(
    x=elev_forbruk.index, 
    y=elev_forbruk.values, 
    order=elev_forbruk.index
    )

# Legg til linje for gjennomsnitt
plt.axhline(
    y=snittforbruk, 
    color="r", 
    linestyle="--", 
    label="Gjennomsnittlig forbruk"
    )

# Pynting
plt.legend()
plt.title("Totalt vannforbruk per elev")
plt.xlabel("Elevnummer")
plt.ylabel("Totalt forbruk")
plt.xticks(rotation=45)
plt.show()

Plotte

Hjelp til sjølvhjelp

Dokumentasjon 🔗

Andre ressursar

KI 🤖

KI 🤖

Forslag til instruks

Jeg skal lage et plot av vannforbruk ved hjelp av pandas, pyplot og seaborn. Datasettet er i langt format og har kolonner "Elev", "Dato", "Ukedag", "Kategori" og "Forbruk". Kategoriene er typisk "Håndvask", "Dusj" osv. Kan du hjelpe meg?

KI 🤖

OBS: Dokumentasjon

Om du bruker KI i arbeidet må du dokumentera bruken slik NDLA viser døme på:

🔗 Dokumenter bruk av KI

Andre tips

  • Få hjelp til å forstå feilmeldingar.
    • Lim inn feilmeldinga og spør om kva som er problemet
  • Få hjelp til å finne logiske feil
    • Lim inn kode for å få tips til kva som ikkje funkar
  • Be om hjelp til å gjera dei berekningane eller laga dei plotta du ønsker.
    Ver så konkret og spesifikk som mogleg.